// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package testing

import (
	"runtime"
)

// AllocPerrun返回调用f期间的平均分配数。
// 虽然返回值的类型为float64，但它始终是一个整数值。
// 
// 要计算分配的数量，函数将首先运行一次，作为
// 预热。然后测量并返回指定
// 运行次数的平均分配数。
// 
// AllocPerrun在测量期间将GOMAXPROCS设置为1，并将在返回前恢复
// 。
func AllocsPerRun(runs int, f func()) (avg float64) {
	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))

	// 预热函数
	f()

	// 测量开始统计
	var memstats runtime.MemStats
	runtime.ReadMemStats(&memstats)
	mallocs := 0 - memstats.Mallocs

	// 运行函数指定次数
	for i := 0; i < runs; i++ {
		f()
	}

	// 读取最终统计
	runtime.ReadMemStats(&memstats)
	mallocs += memstats.Mallocs

	// 在运行期间平均malloc（不计算预热）。
	// 我们被迫返回一个float64，因为API很愚蠢，但是请将除法改为整数，这样我们就可以询问AllocPerrun（）==1 
	// 而不是AllocPerrun（）<2。
	return float64(mallocs / uint64(runs))
}
